package com.example.demo.utils;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.entity.pojo.BaseEntityPoJo;
import com.example.demo.common.entity.response.BaseResponse;
import com.example.demo.common.entity.response.Rs;
import org.springframework.beans.BeanUtils;
import org.springframework.lang.NonNull;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * 通用工具类.
 *
 * @author Mei Ruoxiao
 * @since 2020/9/11
 */
public class CommonUtils {

    public static boolean isErrorId(Long id) {
        if (id == null || id <= 0) {
            return true;
        }
        return false;
    }

    public static JSONObject getIdResponse(Long id) {
        JSONObject object = new JSONObject();
        object.put("id", id);
        return object;
    }

    public static List<Long> splitToLong(final String str) {
        return StringUtils.isEmpty(str) ? Collections.emptyList() : Stream.of(str.split(",")).map(Long::valueOf).collect(Collectors.toList());
    }

    public static <R extends BaseResponse> Rs.JsonInstance getResponse(@NonNull final Page<R> page) {
        return Rs.json().put("response", page).put("totalPage", totalPage(page.getTotal(), (int) page.getSize()));
    }

    public static <T, R> List<R> toList(final List<T> list, @NonNull final Function<T, R> mapFunction) {
        return list.stream().map(mapFunction).collect(Collectors.toList());
    }

    public static <T, R> List<R> toList(final List<T> list, @NonNull final Function<T, R> mapFunction, final Predicate<R> filterFunction) {
        return (Objects.isNull(filterFunction) ? list.stream().map(mapFunction).collect(Collectors.toList()) : list.stream().map(mapFunction).filter(filterFunction).collect(Collectors.toList()));
    }


    public static <T extends BaseEntityPoJo, R> Page<R> toPage(final Page<T> page, @NonNull final Function<T, R> mapFunction) {
        final Page<R> result = new Page();
        if (Objects.isNull(page) || CollectionUtils.isEmpty(page.getRecords())) {
            return result;
        }
        BeanUtils.copyProperties(page, result);
        final Stream<R> stream = page.getRecords().stream().map(mapFunction);
        result.setRecords(stream.collect(Collectors.toList()));
        return result;
    }

    public static <T extends BaseEntityPoJo, R> Page<R> toPage(final Page<T> page, final Function<T, R> mapFunction, final Predicate<R> filterFunction) {
        final Page<R> result = new Page();
        if (Objects.isNull(page) || CollectionUtils.isEmpty(page.getRecords())) {
            return result;
        }
        BeanUtils.copyProperties(page, result);
        if (Objects.nonNull(mapFunction)) {
            final Stream<R> stream = page.getRecords().stream().map(mapFunction);
            result.setRecords(Optional.ofNullable(filterFunction).map(stream::filter).orElse(stream).collect(Collectors.toList()));
        } else {
            final Stream<T> stream2 = (Stream<T>) page.getRecords().stream();
            result.setRecords((List) Optional.ofNullable(filterFunction)
                    .map(filterFunc -> stream2.filter(t -> filterFunc.test((R) t)))
                    .orElse(stream2)
                    .collect(Collectors.toList()));
        }
        return result;
    }

    public static <T extends BaseEntityPoJo> Page<T> toPage(final List<T> list) {
        final Page<T> page = new Page();
        page.setRecords(list);
        page.setTotal(list.size());
        return page;
    }

    public static <T> Page<T> toPage(final List<T> list, final long total, final int page, final int size) {
        final Page<T> pages = new Page();
        pages.setRecords(list);
        pages.setTotal(total);
        pages.setCurrent(page);
        pages.setSize(size);
        return pages;
    }

    public static Long totalPage(final long total, final int size) {
        if (total < size) {
            return 1L;
        } else {
            return (total % size == 0) ? (total / size) : (total / size) + 1;
        }
    }
}
